home *** CD-ROM | disk | FTP | other *** search
- /*
- * fitpolyg.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /* FITPOLYG: program performs polygonal fit upon image lines, where
- * input is in PCC code
- * usage: fitpolyg infile outimg [-t THRESHOLD] [-c] [-w file] [-L]
- */
-
- #define THRESH_DFLT 5
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <images.h>
- #include <string.h>
- #include "tiffimage.h"
- #include "pcc2.h" /* for PCC programs */
- extern void print_sos_lic ();
-
- unsigned char *fcCode; /* code storage */
- long nByteCode; /* no. bytes in code storage */
-
- long xytoline (struct point *, long *, long *, long *);
- long usage (short);
- long input (int, char **, long *, short *, char *);
- float slope (int x1, int y1, int x2, int y2);
-
- main (argc, argv)
- int argc;
- char *argv[];
- {
- Image *imgO; /* pointer to output image structure */
- unsigned char **image; /* output image array */
- long width, height; /* image size */
- struct point imgSize; /* image size */
- long thresh; /* threshold for fit */
- short coordFlag; /* flag = 1, print fit coord.s; or 0 */
- struct point *data; /* data curve */
- long nData; /* no. coords in data curve */
- long nSegments; /* number of segments found */
- long nStructs; /* number of line structures found */
- long kLine; /* line number */
- long lengthSqr, area; /* length sqr.ed and area of line fits */
- long deltaX, deltaY; /* x and y increments for line fits */
- long drawline8 (); /* joins points in 8-connected lines */
- long nFits; /* number of polygonal fits */
- struct point pt0, pt1; /* points to connect fits between */
- long x, y;
- long i;
- char segfile[256];
- int segfileFlag = 0;
- FILE *segstream;
-
- segfile[0] = '\0';
- /* user input */
- if (input (argc, argv, &thresh, &coordFlag, segfile) < 0)
- return (-1);
-
- if (strlen (segfile)) {
- segfileFlag = 1;
- segstream = fopen (segfile, "w+");
- fprintf (segstream, " \n"); /* write blanks for later fseek */
- }
-
- /* open input PCC file */
- if (pccread (argv[1], &fcCode, &nByteCode, &width, &height) == -1)
- exit (1);
- if (!coordFlag)
- printf ("image size: %dx%d, PCC length = %d\n", width, height, nByteCode);
- imgSize.x = width;
- imgSize.y = height;
-
- /* allocate space for data coordinate array */
- if ((data = (struct point *)
- calloc (nByteCode * MAXPERCODE, sizeof (long))) == NULL) {
- printf ("FITPOLYG: not enough memory -- sorry");
- return (-1);
- }
-
- /* construct tables of feature chain decodes */
- pccdecodes ();
-
- /* perform feature chain decoding */
- pcc2xy (data, &nData);
-
- data[nData++].x = -STOPCODE;
- if ((data = (struct point *)
- realloc (data, nData * sizeof (struct point))) == NULL) {
- printf ("FITPOLYG: not enough memory -- sorry");
- return (-2);
- }
-
- /* find x,y coordinates for each line */
- if (xytoline (data, &nData, &nSegments, &nStructs) < 0)
- return (-1);
-
- /* allocate output image */
- imgO = ImageAlloc (height, width, 8);
- image = ImageGetPtr (imgO);
-
- /* initialize image */
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- image[y][x] = 255;
-
- /* determine polygonal fits */
- kLine = 0;
- for (i = 0, nFits = 0; i < nData; i++) {
- if (data[i].x != -1) {
- pt0.x = data[i].x;
- pt0.y = data[i].y;
- i++;
- if (data[i].x < 0) { /* one pixel line */
- image[pt0.y][pt0.x] = 255;
- if (coordFlag != 0)
- printf ("%d: (%d,%d) (%d,%d) %d\n", nFits, pt0.x, pt0.y, pt0.x, pt0.y, kLine);
- if (segfileFlag)
- fprintf (segstream, "%4d %3d %3d %3d %3d %7.2f %3d\n",
- nFits, pt0.x, pt0.y, pt0.x, pt0.y,
- slope (pt0.x, pt0.y, pt0.x, pt0.y), kLine);
- nFits++;
- kLine++;
- }
- lengthSqr = area = 0;
- while (data[i].x >= 0) {
- x = data[i].x - pt0.x;
- y = data[i].y - pt0.y;
- deltaX = data[i].x - data[i - 1].x;
- deltaY = data[i].y - data[i - 1].y;
- lengthSqr += 2 * (x * deltaX + y * deltaY)
- + deltaX * deltaX + deltaY * deltaY;
- area += x * deltaY - y * deltaX;
- if ((area * area) > (thresh * lengthSqr)) {
- pt1.x = data[i].x;
- pt1.y = data[i].y;
- drawline8 (image, imgSize, pt0, pt1, 0);
- if (coordFlag != 0)
- printf ("%d: (%d,%d) (%d,%d) %d\n", nFits, pt0.x, pt0.y, pt1.x, pt1.y, kLine);
- if (segfileFlag)
- fprintf (segstream, "%4d %3d %3d %3d %3d %7.2f %3d\n",
- nFits, pt0.x, pt0.y, pt1.x, pt1.y,
- slope (pt0.x, pt0.y, pt1.x, pt1.y), kLine);
- nFits++;
- pt0.x = data[i].x;
- pt0.y = data[i].y;
- lengthSqr = area = 0;
- }
- i++;
- }
- if (lengthSqr > 0) {
- pt1.x = data[i - 1].x;
- pt1.y = data[i - 1].y;
- drawline8 (image, imgSize, pt0, pt1, 0);
- if (coordFlag != 0)
- printf ("%d: (%d,%d) (%d,%d) %d\n", nFits, pt0.x, pt0.y, pt1.x, pt1.y, kLine);
- if (segfileFlag)
- fprintf (segstream, "%4d %3d %3d %3d %3d %7.2f %3d\n",
- nFits, pt0.x, pt0.y, pt1.x, pt1.y,
- slope (pt0.x, pt0.y, pt1.x, pt1.y), kLine);
- nFits++;
- }
- kLine++;
- --i;
- }
- }
-
- if (!coordFlag)
- printf ("Number of segments fit to data = %d.\n", nFits);
-
- if (segfileFlag) {
- fseek (segstream, 0L, SEEK_SET);
- fprintf (segstream, "%d %d %d", nFits, width, height);
- fclose (segstream);
- }
- /* write image output file */
- ImageOut (argv[2], imgO);
-
- return (0);
- }
-
-
-
- /* USAGE: function gives instructions on usage of program
- * usage: usage (flag)
- * When flag is 1, the long message is given, 0 gives short.
- */
-
- long
- usage (flag)
- short flag; /* flag =1 for long message; =0 for short message */
- {
-
- /* print short usage message or long */
- printf ("USAGE: fitpolyg infile outimg [-t THRESHOLD] [-c] [-w file] [-L]\n");
- if (flag == 0)
- return (-1);
-
- printf ("\nfitpolyg performs polygonal line fitting to image\n");
- printf ("lines; straight line fits are made to portions of each segment\n");
- printf ("to best approximate the chain of points comprising the segment;\n");
- printf ("a segment is a chain of points between features, either\n");
- printf ("endpoint features or junction features.\n\n");
- printf ("ARGUMENTS:\n");
- printf (" infile: input filename (PCC)\n");
- printf (" outimg: output image filename (TIF)\n\n");
- printf ("OPTIONS:\n");
- printf (" -t THRESH: threshold on error for polygonal fit (default = %d);\n", THRESH_DFLT);
- printf (" the smaller is this threshold, the closer will be the\n");
- printf (" polygonal fit to the original data, but the more straight\n");
- printf (" line fit segments will be required.\n");
- printf (" -c: when set, prints out the (x,y) coordinates of the\n");
- printf (" polygonal fit endlines.\n");
- printf (" -w file: save line segment data to a file(.seg) for analysis by xsgll\n");
- printf (" -L: print Software License for this module\n");
-
- return (-1);
- }
-
-
- /* INPUT: function reads input parameters
- * usage: input (argc, argv, &thresh, &coordFlag)
- */
-
- #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
-
- long
- input (argc, argv, thresh, coordFlag, segfile)
- int argc;
- char *argv[];
- long *thresh; /* threshold on polygonal fit */
- short *coordFlag; /* flag = 1, print coordinates of fit; or 0 */
- char *segfile; /* filename for saving segment data */
- {
- long n;
-
- if (argc == 1)
- USAGE_EXIT (1);
- if (argc == 2)
- USAGE_EXIT (0);
-
- *thresh = THRESH_DFLT;
- *coordFlag = 0;
-
- for (n = 3; n < argc; n++) {
- if (strcmp (argv[n], "-t") == 0) {
- if (++n == argc)
- usage (0);
- *thresh = (long) atol (argv[n]);
- }
- if (strcmp (argv[n], "-w") == 0) {
- if (++n == argc)
- usage (0);
- strcpy (segfile, argv[n]);
- }
- else if (strcmp (argv[n], "-c") == 0)
- *coordFlag = 1;
- else if (strcmp (argv[n], "-L") == 0) {
- print_sos_lic ();
- exit (0);
- }
- else
- USAGE_EXIT (0);
- }
-
-
- return (0);
- }
-
- float
- slope (int x1, int y1, int x2, int y2)
- {
- float m;
-
- if ((x2 - x1) == 0) {
- if (y2 - y1 == 0)
- m = (float) 0.0;
- else
- m = (float) 512.0; /* slope = 512/1 */
- }
- else
- m = ((float) (y2 - y1)) / ((float) (x2 - x1));
-
- return (m);
- }
-